package com.deer.wms.ware.task.web;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.deer.wms.base.system.constant.BaseSystemConstant;
import com.deer.wms.base.system.model.Area.AreaInfo;
import com.deer.wms.base.system.model.Cell.CellInfo;
import com.deer.wms.base.system.model.Pack.PackDetail;
import com.deer.wms.base.system.service.AreaInfoService;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.base.system.service.PackDetailService;
import com.deer.wms.intercept.annotation.User;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryCriteria;
import com.deer.wms.inventory.model.Inventory.InventorySelectDto;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.inventory.service.SerialNoService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.core.result.Result;
import com.deer.wms.project.root.core.result.ResultGenerator;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.util.*;
import com.deer.wms.system.manage.model.user.UserInfo;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.system.manage.service.UserInfoService;
import com.deer.wms.system.manage.service.ValidatorService;
import com.deer.wms.ware.task.config.StrategyErpService;
import com.deer.wms.ware.task.constant.WareTaskConstant;
import com.deer.wms.ware.task.erp.UpdatePPF;
import com.deer.wms.ware.task.model.Box.BoxDetail;
import com.deer.wms.ware.task.model.SO.DeliveryData;
import com.deer.wms.ware.task.model.SO.Merge;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.model.Wave.WaveDetail;
import com.deer.wms.ware.task.model.Wave.WaveMaster;
import com.deer.wms.ware.task.model.out.OutDetail;
import com.deer.wms.ware.task.model.pickTask.*;
import com.deer.wms.ware.task.model.pushErp.beasAssist.BaseAssist;
import com.deer.wms.ware.task.service.*;
import com.deer.wms.ware.task.service.impl.SoMasterServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.activation.DataHandler;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.CollectionUtils.convertMap;
import static com.deer.wms.project.root.util.PageUtils.getStart;

/**
 * @author guo
 * @since 2020/02/02
 */
@RestController
@RequestMapping("/pick/tasks")
@Transactional

public class PickTaskController {

    @Autowired
    private PushErpService pushErpService;
    @Autowired
    private PickTaskService pickTaskService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private SoDetailService soDetailService;
    @Autowired
    private SoMasterServiceImpl soMasterService;
    @Autowired
    private WaveDetailService waveDetailService;
    @Autowired
    private PackDetailService packDetailService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private ValidatorService validatorService;
    @Autowired
    private SerialNoService serialNoService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private CodeRuleService codeRuleService;

    @Autowired
    private WaveMasterService waveMasterService;

    @Autowired
    private StrategyErpService strategyErpService;

    @PostMapping
    public Result add(@RequestBody PickTask pickTask) {
        pickTaskService.save(pickTask);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 手工分配库存
     *
     * @param createPickTask
     * @return
     */
    @PostMapping("/manualCreatePickTask")
    @Transactional
    public Result manualCreatePickTask(@RequestBody CreatePickTask createPickTask, @ApiIgnore @User CurrentUser currentUser) {
        List<UpdatePPF> ppfList = new ArrayList<>();

        if (createPickTask.getBillNo().equals("") || createPickTask.getSoDetailId() == null || createPickTask.getCreatePickTaskDetails().size() <= 0) {
            return ResultGenerator.genFailResult(CommonCode.PARAMETER_ERROR);
        }
        List<PickTaskDto> list = pickTaskService.findList(new PickTaskCriteria(createPickTask.getSoDetailId(), 4));
        if (list.size() > 0) {
            return ResultGenerator.genFailResult(CommonCode.PICK_TASK_ALREADY_EXIST);
        }
        SoDetail soDetail = soDetailService.getById(createPickTask.getSoDetailId());

        if (ObjectUtil.isNotEmpty(soDetail.getWaveDetailId())) {
            WaveDetail waveDetail = waveDetailService.getById(soDetail.getWaveDetailId());
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该任务单已被" + waveDetail.getWaveCode() + "合并，请在" + waveDetail.getWaveCode() + "分配");
        }
        SoMaster soMaster = soMasterService.findBy("bill_no", createPickTask.getBillNo());
        soMaster.setAssUserId(createPickTask.getUserId());
        soDetail.setPickUserId(createPickTask.getUserId());
        UserInfo userinfo = userInfoService.getById(createPickTask.getUserId());
        soDetail.setPickUserName(userinfo.getUserName());
        soMaster.setAssUserName(userinfo.getUserName());
        //分配数量
        double allottedQuantity = 0;
        for (CreatePickTaskDetail createPickTaskDetail : createPickTask.getCreatePickTaskDetails()) {
            InventorySelectDto inventorySelectDto = inventoryService.findByInventoryId(new InventoryCriteria(createPickTaskDetail.getInventoryId())).get(0);
            //发运单的单位
            PackDetail packDetail = packDetailService.getById(soDetail.getPackDetailId());
            //拣货任务的单位
            PackDetail packDetailPick = packDetailService.getById(createPickTaskDetail.getPackDetailId());
            /**
             * 涉及到转换率
             */
//            double quantity = MyUtils.calculateDivide(soDetail.getPackDetailId(), inventorySelectDto.getPackDetailId(), createPickTaskDetail.getPickQuantity(), packDetail.getTransRatio());
            double quantity = createPickTaskDetail.getPickQuantity();
            inventorySelectDto.setAllotQuantity((inventorySelectDto.getAllotQuantity() == null ? 0.0 : inventorySelectDto.getAllotQuantity()) + quantity);
            inventoryService.updateById(inventorySelectDto);
            PickTask pickTask = new PickTask(
                    soDetail.getSoDetailId(),
                    soMaster.getSoMasterId(),
                    soMaster.getWareId(),
                    soMaster.getWareName(),
                    soMaster.getOrganizationId(),
                    soMaster.getOrganizationName(),
                    inventorySelectDto.getAreaCode(),
                    inventorySelectDto.getAreaName(),
                    inventorySelectDto.getShelfCode(),
                    inventorySelectDto.getShelfName(),
                    inventorySelectDto.getCellCode(),
                    inventorySelectDto.getCellName(),
                    inventorySelectDto.getItemCode(),
                    inventorySelectDto.getItemName(),
                    inventorySelectDto.getBatchId(),
                    inventorySelectDto.getBatchName(),
                    inventorySelectDto.getBoxCode(),
                    inventorySelectDto.getLpn(),
                    soDetail.getPackDetailId(),
                    soDetail.getPackDescribe(),
                    createPickTaskDetail.getPickQuantity(),
                    0,
                    inventorySelectDto.getInventoryId(),
                    1,
                    soDetail.getImgUrl()
            );
            pickTask.setPackDetailId(packDetailPick.getPackDetailId());
            pickTask.setPackDescribe(packDetailPick.getPackDescribe());
            pickTaskService.save(pickTask);
            UpdatePPF updatePPF = new UpdatePPF();
            updatePPF.setBillId(soDetail.getErpBillId());
            updatePPF.setCommitQty(createPickTaskDetail.getPickQuantity());
            updatePPF.setRowIndex(soDetail.getBomSplit());
            ppfList.add(updatePPF);
            allottedQuantity += createPickTaskDetail.getPickQuantity();
            Integer invenotryId = createPickTaskDetail.getInventoryId();
            Inventory inventory = inventoryService.getById(invenotryId);
            inventory.setAllotQuantity(createPickTaskDetail.getPickQuantity());
            //拣货分配
//            savePickTask(pickTask, currentUser);
        }

        soDetail.setAllottedQuantity(allottedQuantity + soDetail.getAllottedQuantity());
        soDetailService.updateById(soDetail);
        soMasterService.updateState(soMaster);
        if ("88".equals(soMaster.getBillType())) {
            pushErpService.UpdatePPFeedAssignedQty(ppfList);
        }

        return ResultGenerator.genSuccessResult();
    }


    public void savePickTask(PickTask pickTask, CurrentUser currentUser) {
        pickTask.setToBoxCode(codeRuleService.generateCellCodeRedis());
        //Step2.拣货确认
        pickTaskService.commitPick(pickTask, currentUser);
    }



    /**
     * 自动分配库存
     *
     * @param merge 合并的SO单号
     * @return Result
     */
    @PostMapping("/autoCreatePickTask")
    public Result autoCreatePickTask(@RequestBody Merge merge, @ApiIgnore @User CurrentUser currentUser) {
        List<SoMaster> soMasters = soMasterService
                .list(new QueryWrapper<SoMaster>().in("bill_no", merge.getBillNos()));
        //校验SO的状态，只允许初始化的单据能生成波次
        for (SoMaster soMaster : soMasters) {
            if (ObjectUtil.equal(soMaster.getState(), WareTaskConstant.SO_STATE_INIT)
                    || ObjectUtil.equal(soMaster.getState(), WareTaskConstant.SO_STATE_OUTOFSTOCK)) {
                pickTaskService.createPickTaskWin(soMaster.getBillNo(), currentUser);
            }
        }

        return ResultGenerator.genSuccessResult();
    }



    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        pickTaskService.removeById(id);
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/update")
    public Result update(@RequestBody PickTask pickTask) {
        pickTaskService.updateById(pickTask);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/{id}")
    public Result detail(@PathVariable Integer id) {
        PickTask pickTask = pickTaskService.getById(id);
        return ResultGenerator.genSuccessResult(pickTask);
    }

    @GetMapping("/list")
    public Result list(PickTaskCriteria criteria) {
        StringUtil.trimObjectStringProperties(criteria);
        // criteria.setWaveCode(criteria.getWaveCode().trim());
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<PickTaskDto> list = pickTaskService.findList(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("pageList")
    public Result pageList(PickTaskCriteria criteria) {
        Integer pageNum = criteria.getPageNum();
        criteria.setPageNum(getStart(criteria));
        List<PickTaskDto> list = pickTaskService.findPageList(criteria);
        PageInfo pageInfo = new PageInfo(list);
        pageInfo.setPageNum(pageNum);
        pageInfo.setTotal(pickTaskService.findCount(criteria));
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/findBySoMasterId")
    public Result findBySoMasterId(PickTaskCriteria criteria) {
        StringUtil.trimObjectStringProperties(criteria);
        // criteria.setWaveCode(criteria.getWaveCode().trim());
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<PickTaskDto> list = pickTaskService.findByBillNo(criteria);
        PageInfo pageInfo = new PageInfo(list.stream().filter(item -> item.getState() == 0).collect(Collectors.toList()));
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/findByWaveId")
    public Result findByWaveId(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());

        //首选需要判定波次明细是否已经完全推荐，因为存在波次部分推荐的情况
        WaveDetail waveDetail = waveDetailService.getById(criteria.getWaveId());
//        if (WareTaskConstant.WAVE_STATE_PICKING.equals(waveDetail.getState())) {
//            // 若没有完全推荐，则需要根据库存重新推荐
//            UserInfo wareUser = userInfoService.getById(waveDetail.getPickUserId());
//            waveDetailService.suggestForPick(Collections.singletonList(waveDetail), wareUser, currentUser);
//        }

        //获取当前波次明细下的所有拣货任务
        List<PickTaskDto> list = pickTaskService.findByWave(criteria.getWaveId());
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @Autowired
    private AreaInfoService areaInfoService;

    @GetMapping("pickErp")
    public Result pickErp(String pickIds) {
        List<String> ids = Arrays.asList(StringUtils.split(pickIds, ","));
        List<PickTask> pickTasks = pickTaskService.listByIds(ids);
        if (pickTasks.listIterator().next().getState() != 6) {
            return ResultGenerator.genSuccessResult();
        }
        ;
        List<Integer> soDetailIds = pickTasks.stream().map(PickTask::getSoDetailId).collect(Collectors.toList());
        List<SoDetail> soDetails = soDetailService.listByIds(soDetailIds);
        List<String> areaCode = pickTasks.stream().map(PickTask::getAreaCode).collect(Collectors.toList());
        List<AreaInfo> areaInfos = areaInfoService.list(new QueryWrapper<AreaInfo>().in("area_code", areaCode));
        Map<Integer, SoDetail> soDetailMap = convertMap(soDetails, SoDetail::getSoDetailId);
        Map<String, AreaInfo> areaInfoMap = convertMap(areaInfos, AreaInfo::getAreaCode);
        List<OutDetail> outDetails = new ArrayList<>();
        for (PickTask pickTask : pickTasks) {
            OutDetail outDetail = new OutDetail();
            SoDetail soDetail = soDetailMap.get(pickTask.getSoDetailId());
            if (ObjectUtil.isEmpty(soDetail)) {
                continue;
            }
            if (ObjectUtil.equals(soDetail.getPickQuantity(), soDetail.getOrderQuantity())) {
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_ALL_PICK);
            } else {
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_PART_PICK);
            }
            BeanUtils.copyProperties(soDetail, outDetail);
            outDetail.setDeliveryQuantity(pickTask.getPickQuantity()); //数量
            outDetail.setBatchName(pickTask.getBatchName());
            AreaInfo areaInfo = areaInfoMap.get(pickTask.getAreaCode());
            outDetail.setErpAreaId(areaInfo.getErpAreaId());
            outDetails.add(outDetail);
            pickTask.setState(5);
        }
        pickTaskService.updateBatchById(pickTasks);
        SoMaster soMaster = soMasterService.getOneByField("bill_no", outDetails.iterator().next().getBillNo());
        strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 波次拣货---直接提交(新增)
     */
    @GetMapping("/wavePick")
    public Result wavePick(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        //新接口
        if (true) {
            pickTaskService.sendWavePick(criteria, currentUser);
            return ResultGenerator.genSuccessResult();
        }

//        List<Integer> waveIds = criteria.getWaveIds();
//        if (waveIds.size() > 3) {
//            throw new ServiceException(CommonCode.AREA_EXISTS, "拣货数量不可大于3");
//        }
//        List<PickTask> list = pickTaskService.list(new QueryWrapper<PickTask>()
//                .in("wave_detail_id", criteria.getWaveIds())
//                .eq("state", 0));
//        for (PickTask pickTask : list) {
//            if (WareTaskConstant.PICK_STATE_ALLPICK.equals(pickTask.getState()) || WareTaskConstant.PICK_STATE_OUTED.equals(pickTask.getState())) {
//                continue;
//            }
//            pickTask.setToBoxCode(codeRuleService.generateCellCodeRedis());
//            // 目标库位
//            String toCellCode = cellInfoService.getSysJhCell(criteria.getWareId());
//            pickTask.setToCellCode(toCellCode);
//            pickTask.setReviewQuantity(pickTask.getPickQuantity());
//            //Step2.拣货确认
//            pickTaskService.commitPick(pickTask, currentUser);
//        }
//
//        //初始化数据 准备回传ERP
////        List<Integer> soDetailIds = list.stream().map(PickTaskDto::getSoDetailId).collect(Collectors.toList());
////        List<PickTaskDto> returnPick = pickTaskService.findByWave(criteria.getWaveId());
//        List<PickTask> returnPick = pickTaskService.list(new QueryWrapper<PickTask>().
//                in("wave_detail_id", criteria.getWaveIds())
//                .eq("state", 2)
//        );
//        //获取任务单明细
//        Set<Integer> soDetailIds = returnPick.stream().map(PickTask::getSoDetailId).collect(Collectors.toSet());
//        List<SoDetail> soDetails = soDetailService.listByIds(soDetailIds);
//        Map<Integer, SoDetail> soDetailMap = convertMap(soDetails, SoDetail::getSoDetailId);
//        List<Integer> invIds = returnPick.stream().map(PickTask::getInventoryId).collect(Collectors.toList());
//        List<Inventory> inventories = inventoryService.listByIds(invIds);
//        Map<Integer, Inventory> invMap = convertMap(inventories, Inventory::getInventoryId);
//        List<OutDetail> outDetails = new ArrayList<>();
//
//        List<SoDetail> updateSoDetail = new ArrayList<>();
//
//
//        //回传ERP
//        for (PickTask pickTaskDto : returnPick) {
//            pickTaskDto.setState(5);
//            Inventory inventory = invMap.get(pickTaskDto.getInventoryId());
//            OutDetail outDetail = new OutDetail();
//            SoDetail soDetail = soDetailMap.get(pickTaskDto.getSoDetailId());
//
//            if (ObjectUtil.isEmpty(soDetail)) {
//                continue;
//            }
//
//            //拣货数量等于分配数量+任务单数量
//            soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + pickTaskDto.getPickQuantity());
//            if (ObjectUtil.equals(soDetail.getPickQuantity(), soDetail.getOrderQuantity())) {
//                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_ALL_PICK);
//            } else {
//                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_PART_PICK);
//            }
//            //拣货 时间
//            soDetail.setPickTime(LocalDateTime.now());
//
//            updateSoDetail.add(soDetail);
//            BeanUtils.copyProperties(soDetail, outDetail);
//            outDetail.setDeliveryQuantity(pickTaskDto.getPickQuantity()); //数量
//            outDetail.setCellCode(inventory.getCellCode());
//            outDetail.setBatchName(inventory.getBatchName());
//            outDetail.setErpAreaId(inventory.getErpAreaId());
//            outDetails.add(outDetail);
//        }
//
//        Set<String> billNos = outDetails.stream().map(OutDetail::getBillNo).collect(Collectors.toSet());
//        pickTaskService.updateBatchById(returnPick);
//
//        SoMaster soMaster = soMasterService.getOneByField("bill_no", outDetails.iterator().next().getBillNo());
//        //批量修改任务单详情状态
//        soDetailService.updateBatchById(updateSoDetail);
//        inventoryService.removeByIds(invIds);
//
//        List<SoMaster> soMasterList = new ArrayList<>();
//        //24生产领料,需要判断是否齐套
//        if (soMaster.getSoType() == 24) {
//            List<SoMaster> soMasters = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", billNos));
//            Map<String, SoMaster> soMasterMap = convertMap(soMasters, SoMaster::getBillNo);
//            soMasterMap.forEach((key, val) -> {
//                if (ObjectUtil.isEmpty(val)) {
//                    return;
//                }
//                if (soMasterService.dispatch(val.getOrderBillNo())&&val.getDispatch()!=2) {
//                    val.setDispatch(1);
//                }
//                else {
//                    val.setDispatch(0);
//                }
//            });
//            soMasterList.addAll(soMasterMap.values());
//        }
//
//        //齐套
//        soMasterService.updateBatchById(soMasterList);
//
//        strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());


        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("sendWavePick")
    /**
     * 波次拣货---直接提交(新)
     */
    public Result sendWavePick(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        pickTaskService.sendWavePick(criteria, currentUser);

        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/soDetailPick")
    public Result soDetailPick(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
//        StrUtil.isAllBlank()
        if (ObjectUtil.isEmpty(criteria.getSoDetailIds())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "请选择明细");
        }
        List<PickTask> list = pickTaskService.list(new QueryWrapper<PickTask>()
                .in("so_detail_id", criteria.getSoDetailIds())
                .eq("state", 0));
        for (PickTask pickTask : list) {
            if (WareTaskConstant.PICK_STATE_ALLPICK.equals(pickTask.getState()) || WareTaskConstant.PICK_STATE_OUTED.equals(pickTask.getState())) {
                continue;
            }
            pickTask.setToBoxCode(codeRuleService.generateCellCodeRedis());
            // 目标库位
            String toCellCode = cellInfoService.getSysJhCell(criteria.getWareId());
            pickTask.setToCellCode(toCellCode);
            pickTask.setReviewQuantity(pickTask.getPickQuantity());
            //Step2.拣货确认
            pickTaskService.commitPick(pickTask, currentUser);
        }
        List<PickTask> returnPick = pickTaskService.list(new QueryWrapper<PickTask>()
                .in("so_detail_id", criteria.getSoDetailIds())
                .eq("state", 2)
        );

        //获取任务单明细
        Set<Integer> soDetailIds = returnPick.stream().map(PickTask::getSoDetailId).collect(Collectors.toSet());
        List<SoDetail> soDetails = soDetailService.listByIds(soDetailIds);
        Map<Integer, SoDetail> soDetailMap = convertMap(soDetails, SoDetail::getSoDetailId);
        List<Integer> invIds = returnPick.stream().map(PickTask::getInventoryId).collect(Collectors.toList());
        List<Inventory> inventories = inventoryService.listByIds(invIds);
        Map<Integer, Inventory> invMap = convertMap(inventories, Inventory::getInventoryId);
        List<OutDetail> outDetails = new ArrayList<>();

        List<SoDetail> updateSoDetail = new ArrayList<>();

        //回传ERP
        for (PickTask pickTaskDto : returnPick) {
            pickTaskDto.setState(5);
            Inventory inventory = invMap.get(pickTaskDto.getInventoryId());
            OutDetail outDetail = new OutDetail();
            SoDetail soDetail = soDetailMap.get(pickTaskDto.getSoDetailId());

            if (ObjectUtil.isEmpty(soDetail)) {
                continue;
            }

            //拣货数量等于分配数量+任务单数量
            soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + pickTaskDto.getPickQuantity());
            if (ObjectUtil.equals(soDetail.getPickQuantity(), soDetail.getOrderQuantity())) {
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_ALL_PICK);
            } else {
                soDetail.setState(WareTaskConstant.SO_DETAIL_STATE_PART_PICK);
            }
            //拣货 时间
            soDetail.setPickTime(LocalDateTime.now());

            updateSoDetail.add(soDetail);
            BeanUtils.copyProperties(soDetail, outDetail);
            outDetail.setDeliveryQuantity(pickTaskDto.getPickQuantity()); //数量
            outDetail.setCellCode(inventory.getCellCode());
            outDetail.setBatchName(inventory.getBatchName());
            outDetail.setErpAreaId(inventory.getErpAreaId());
            outDetails.add(outDetail);
        }

        Set<String> billNos = outDetails.stream().map(OutDetail::getBillNo).collect(Collectors.toSet());
        pickTaskService.updateBatchById(returnPick);

        SoMaster soMaster = soMasterService.getOneByField("bill_no", outDetails.iterator().next().getBillNo());
        //批量修改任务单详情状态
        soDetailService.updateBatchById(updateSoDetail);
        inventoryService.removeByIds(invIds);

        List<SoMaster> soMasterList = new ArrayList<>();
        //24生产领料,需要判断是否齐套
        if (soMaster.getSoType() == 24) {
            List<SoMaster> soMasters = soMasterService.list(new QueryWrapper<SoMaster>().in("bill_no", billNos));
            Map<String, SoMaster> soMasterMap = convertMap(soMasters, SoMaster::getBillNo);
            soMasterMap.forEach((key, val) -> {
                if (ObjectUtil.isEmpty(val)) {
                    return;
                }
                if (soMasterService.dispatch(val.getOrderBillNo())&&val.getDispatch()!=2) {
                    val.setDispatch(1);
                }
                else {
                    val.setDispatch(0);
                }
            });
            soMasterList.addAll(soMasterMap.values());
        }

        //齐套
        soMasterService.updateBatchById(soMasterList);

        strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());

        return ResultGenerator.genSuccessResult();

    }

    @GetMapping("/findByDetailId")
    public Result findByDetailId(@RequestParam Integer soDetailId) {
        List<PickTask> list = pickTaskService.findBySoDetailId(soDetailId);
        return ResultGenerator.genSuccessResult(list);
    }

    @GetMapping("/allotTask")
    public Result allotTask(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        StringUtil.trimObjectStringProperties(criteria);
        // criteria.setWaveCode(criteria.getWaveCode().trim());
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        criteria.setUserId(currentUser.getUserId());
        List<PickTaskDto> list = pickTaskService.allotTask(criteria);
        for (PickTaskDto pickTask : list) {
            if (pickTask.getAllotUserId() == null) {
                pickTask.setAllotTime(DateUtils.getNowDateTimeString());
                pickTask.setAllotUserId(currentUser.getUserId());
                pickTask.setAllotUserName(currentUser.getUserName());
                pickTaskService.updateById(pickTask);
            }
        }
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("/boxingList")
    public Result boxingList(PickTaskCriteria criteria) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<PickTaskDto> list = new ArrayList<>();
        if (criteria.getTag() == 1) {
            list = pickTaskService.findBySo(criteria.getBillNo());

        } else if (criteria.getTag() == 2) {
            list = pickTaskService.findByWave(criteria.getWareId());
        }
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @PostMapping("/findFirst")
    public Result findFirst(@RequestBody PickTaskCriteria criteria) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        List<PickTaskDto> list = pickTaskService.findFirst(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @PostMapping("/cancelPickTask")
    @Transactional
    public Result cancelPickTask(@RequestBody PickTaskCriteria pickTaskCriteria) {
        List<UpdatePPF> updatePPFS = new ArrayList<>();
        List<PickTaskDto> list = pickTaskService.findList(pickTaskCriteria);
        List<Integer> soMasterIds = list.stream().map(item -> item.getSoMasterId()).collect(Collectors.toList());
        List<SoMaster> soMasters = soMasterService.listByIds(soMasterIds);
        Map<Integer, SoMaster> soMasterMap = convertMap(soMasters, SoMaster::getSoMasterId);

        for (PickTaskDto pickTask : list) {
            if (pickTask.getState() == 3) {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "任务单已撤销，不可重复撤销");
            }
            pickTask.setState(WareTaskConstant.PICK_STATE_CANCELED);
            pickTaskService.updateById(pickTask);
            Inventory inventory = inventoryService.getById(pickTask.getInventoryId());
            if (ObjectUtil.isNotEmpty(inventory)) {
                inventory.setAllotQuantity(inventory.getAllotQuantity() - pickTask.getPickQuantity());
                inventoryService.updateById(inventory);
            }
            /**
             * 涉及到转换率
             */
//            double quantity = MyUtils.calculateMultiplication(inventory.getPackDetailId(), pickTask.getPackDetailId(), pickTask.getPickQuantity(), pickTask.getTransRatio());
            SoDetail soDetail = soDetailService.getById(pickTask.getSoDetailId());
            WaveDetail waveDetail = waveDetailService.getById(pickTask.getWaveDetailId());
            if (ObjectUtil.isNotEmpty(waveDetail)) {
                waveDetail.setAllottedQuantity(waveDetail.getAllottedQuantity()-pickTask.getPickQuantity());
                waveDetailService.updateById(waveDetail);
            }
            if (ObjectUtil.isEmpty(soDetail)) {
                continue;
            }
            if (soDetail.getAllottedQuantity() < 0) {
                soDetail.setAllottedQuantity(0.00);
            } else {
                 soDetail.setAllottedQuantity(soDetail.getAllottedQuantity() - pickTask.getPickQuantity());
            }

            if (ObjectUtil.isNotEmpty(soMasterMap.get(pickTask.getSoMasterId()).getBillType()) && soMasterMap.get(pickTask.getSoMasterId()).getBillType() == 88) {
                UpdatePPF updatePPF = new UpdatePPF();
                updatePPF.setBillId(soDetail.getErpBillId());
                updatePPF.setCommitQty(0 - pickTask.getPickQuantity());
                updatePPF.setRowIndex(soDetail.getBomSplit());
                soDetailService.updateById(soDetail);
                updatePPFS.add(updatePPF);
            }
            ;

        }


        //退回
        if (ObjectUtil.isNotEmpty(updatePPFS)) {
            try {
                pushErpService.UpdatePPFeedAssignedQty(updatePPFS);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return ResultGenerator.genSuccessResult();
    }

    @Autowired
    private CellInfoService cellInfoService;

    /**
     * 拣货任务 直接确认拣货
     */
    @PostMapping("/pickTaskAffirm")
    @Transactional
    public Result pickTaskAffirm(@RequestBody PickTaskCriteria pickTaskCriteria, @ApiIgnore @User CurrentUser currentUser) {
        //Step1.校验
        // 目标库位； 任务状态；
        String cellCode = pickTaskCriteria.getToCellCode();
        CellInfo cellInfo = cellInfoService.findByCodeAndWareId(cellCode, pickTaskCriteria.getWareId());
        if (ObjectUtil.notEqual(BaseSystemConstant.CELL_USE_TYPE_COLLECTION, cellInfo.getCellUseType())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该货位不是集货位，不支持拣货");
        }
        Integer pickTaskId = pickTaskCriteria.getPickTaskId();
        PickTask pickTask = pickTaskService.getById(pickTaskId);
        if (ObjectUtil.equals(WareTaskConstant.PICK_STATE_ALLPICK, pickTask.getState())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该任务已经拣货完成！");
        }
        if (Objects.equals(pickTask.getState(), WareTaskConstant.PICK_STATE_MERGED)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "该任务已合并，不支持拣货");
        }

        List<PickTaskDto> pickTaskDtos = pickTaskService.getChildTasksByParentId(pickTaskId);
        if (pickTaskDtos.size() == 0) {
            pickTaskDtos.add(pickTaskService.getTaskById(pickTaskId));
        }
        if (pickTaskDtos.size() == 0) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "");
        }
        for (PickTaskDto pickTaskDto : pickTaskDtos) {
            //涉及到转换率
            Inventory inventory = inventoryService.getById(pickTaskDto.getInventoryId());

//            double quantity = MyUtils.calculateMultiplication(inventory.getPackDetailId(), pickTaskDto.getPackDetailId(), pickTaskDto.getPickQuantity(), pickTaskDto.getTransRatio());
            inventory.setAllotQuantity(inventory.getAllotQuantity() - pickTaskDto.getPickQuantity());
            inventoryService.updateById(inventory);
            pickTask.setToCellCode(cellCode);
            pickTaskService.commitPick(pickTask, currentUser);
            pickTask.setState(5);
            pickTaskService.updateById(pickTask);
//            if(!CollectionUtils.isEmpty(pickTaskCriteria.getSerialNos())){
//                serialNoService.serialNoRecored(pickTaskCriteria.getSerialNos(), currentUser.getUserId(), currentUser.getUserName(),
//                        pickTaskDto.getPickTaskId(), inventory.getInventoryId(), InventoryConstant.SERIALNO_CHECKANDACCEPT);
//            }
        }
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/warePickTask")
    public Result warePickTask(@RequestBody PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        List<PickTaskDto> list = pickTaskService.findList(criteria);
        return ResultGenerator.genSuccessResult();
    }

    /*@PostMapping("/as")
    public Result as(@RequestBody PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if(currentUser == null){
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER, null);
        }
        String tableName = "so_master";
        Integer nextId = validatorService.getNextId(tableName);
        String mergeNo = "HB"+"-"+ nextId;
        System.out.print("hanhna");
        *//*for(int i=0;i<merge.getBillNos().size();i++){
            String billNo = merge.getBillNos().get(i);
            SoMaster soMaster = soMasterService.findBy("bill_no",billNo);
            soMaster.setMergeNo(mergeNo);
            soMaster.setState(11);
            soMasterService.updateById(soMaster);

            SoDetailCriteria criteria = new SoDetailCriteria();
            criteria.setBillNo(billNo);
            List<SoDetailDto> soDetails = soDetailService.findList(criteria);
            for(int y=0;y<soDetails.size();y++){
                SoDetail soDetail = soDetails.get(y);
                soDetail.setMergeNo(mergeNo);
                soDetailService.updateById(soDetail);
            }

        }

        SoMasterCriteria criteria = new SoMasterCriteria();
        criteria.setBillNos(merge.getBillNos());
        List<SoMaster> soMasters = soMasterService.findList(criteria);
        SoMaster soMaster = new SoMaster();
        DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");

        Date d4 = dateFormat.parse(DateUtils.getNowDateTimeString());
        Date d5 = dateFormat.parse(DateUtils.getNowDateTimeString());
        Date d6 = dateFormat.parse(DateUtils.getNowDateTimeString());


        for(int i = 0; i < soMasters.size(); i++) {
            SoMaster soMaster1 = soMasters.get(i);

            String deliveryTime = soMaster1.getDeliveryTime();
            String expectTimeFm = soMaster1.getExpectTimeFm();
            String expectTimeTo = soMaster1.getExpectTimeTo();

            if (i == 0) {
                d4 = dateFormat.parse(deliveryTime);
                d5 = dateFormat.parse(expectTimeFm);
                d6 = dateFormat.parse(expectTimeTo);

                soMaster.setDeliveryTime(deliveryTime);
                soMaster.setExpectTimeFm(expectTimeFm);
                soMaster.setExpectTimeTo(expectTimeTo);
            }

            Date d1 = dateFormat.parse(deliveryTime);
            Date d2 = dateFormat.parse(expectTimeFm);
            Date d3 = dateFormat.parse(expectTimeTo);

            if (d1.before(d4)) {
                soMaster.setDeliveryTime(deliveryTime);
            }
            if (d2.before(d5)) {
                soMaster.setExpectTimeFm(expectTimeFm);
            }
            if (d3.before(d6)) {
                soMaster.setExpectTimeTo(expectTimeTo);
            }
            soMaster.setWareId(soMaster1.getWareId());
            soMaster.setWareName(soMaster1.getWareName());
            soMaster.setOrganizationId(soMaster1.getOrganizationId());
            soMaster.setOrganizationName(soMaster1.getOrganizationName());
            soMaster.setCustomerId(soMaster1.getCustomerId());
            soMaster.setCustomerName(soMaster1.getCustomerName());
            soMaster.setCarrierId(soMaster1.getCarrierId());
            soMaster.setCarrierName(soMaster1.getCarrierName());
            soMaster.setCreateTime(DateUtils.getNowDateTimeString());
            soMaster.setCreateUserId(currentUser.getUserId());
            soMaster.setCreateUserName(currentUser.getUserName());
            soMaster.setOrderNo(soMaster1.getOrderNo());
            soMaster.setInsertType(soMaster1.getInsertType());
            soMaster.setSoUdfHs1(soMaster1.getSoUdfHs1());
            soMaster.setSoUdfHs2(soMaster1.getSoUdfHs2());
            soMaster.setSoUdfHs3(soMaster1.getSoUdfHs3());
            soMaster.setMemo(soMaster1.getMemo());
            soMaster.setReceivingAddressId(soMaster1.getReceivingAddressId());
            soMaster.setLinkMan(soMaster1.getLinkMan());
            soMaster.setLinkPhone(soMaster1.getLinkPhone());
            soMaster.setProvince(soMaster1.getProvince());
            soMaster.setCity(soMaster1.getCity());
            soMaster.setArea(soMaster1.getArea());
            soMaster.setDetailAddress(soMaster1.getDetailAddress());
        }
        soMaster.setState(0);
        soMaster.setCaseState(2);
        soMaster.setBillNo(mergeNo);
        soMaster.setBillSource(2);
        soMaster.setMergeNo(null);

        soMasterService.save(soMaster);*//*

        return ResultGenerator.genSuccessResult("");
    }*/

    /**
     * 按订单复核
     *
     * @param boxDetail
     * @return
     */
    @PostMapping("/checkBySo")
    public Result checkBySo(@RequestBody BoxDetail boxDetail) {
        String time = DateUtils.getNowDateTimeString();
        PickTask pickTask = pickTaskService.getById(boxDetail.getPickTaskId());
        pickTask.setReviewQuantity(pickTask.getReviewQuantity() + boxDetail.getQuantity());
        pickTaskService.updateById(pickTask);

        SoDetail soDetail = soDetailService.getById(boxDetail.getSoDetailId());
        soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + boxDetail.getQuantity());
        soDetailService.updateById(soDetail);

        SoMaster soMaster = soMasterService.getById(boxDetail.getSoMasterId());
        soMaster.setActualDeliveryTime(time);
        soMasterService.updateById(soMaster);
        return ResultGenerator.genSuccessResult();
    }


    @ApiOperation(value = "批量发货", notes = "批量发货")
    @PostMapping("/delivery")
    public Result delivery(@RequestBody DeliveryData deliveryData) {
        for (int i = 0; i < deliveryData.getPickTasks().size(); i++) {
            //step1.生成库存事务
            PickTask pickTask = deliveryData.getPickTasks().get(i);
            InventoryTransact inventoryTransact = new InventoryTransact();
            inventoryTransact.setTransactType(InventoryConstant.SERIALNO_OUT);
            inventoryTransact.setFromBatchId(pickTask.getBatchId());
            inventoryTransact.setFromBatchName(pickTask.getBatchName());
            inventoryTransact.setWareId(pickTask.getWareId());
            inventoryTransact.setWareName(pickTask.getWareName());
            inventoryTransact.setToCellCode(pickTask.getToCellCode());
            inventoryTransact.setToBatchId(pickTask.getBatchId());
            inventoryTransact.setToBatchName(pickTask.getBatchName());
            inventoryTransact.setItemCode(pickTask.getItemCode());
            inventoryTransact.setItemName(pickTask.getItemName());
            inventoryTransact.setToBoxCode(pickTask.getBoxCode());
            inventoryTransact.setToPackDetailId(pickTask.getPackDetailId());
            inventoryTransact.setToPackDescribe(pickTask.getPackDescribe());
            inventoryTransact.setToTransRatio(0.0);
            inventoryTransact.setCreateUserId(pickTask.getCheckUserId());
            inventoryTransact.setCreateUserName(pickTask.getCheckUserName());
            inventoryTransact.setCreateTime(pickTask.getCheckTime());
            inventoryTransact.setToQuantity(pickTask.getPickQuantity());
            inventoryTransact.setToOrganizationId(pickTask.getOrganizationId());
            inventoryTransact.setToOrganizationName(pickTask.getOrganizationName());
            inventoryTransactService.save(inventoryTransact);

            //step2.修改SO明细的状态 部分发货、全部发货
            Integer soDetailId = pickTask.getSoDetailId();
            SoDetail soDetail = soDetailService.getById(soDetailId);
            soDetail.setDeliveryQuantity(pickTask.getPickQuantity());
            if (soDetail.getDeliveryQuantity().equals(soDetail.getOrderQuantity())) {
                soDetail.setState(2); //全部发货
            } else {
                soDetail.setState(1); //部分发货

            }
            soDetailService.updateById(soDetail);

            inventoryTransact.setDetailNo(soDetail.getDetailNo());
            inventoryTransactService.updateById(inventoryTransact);

            //step3.修改拣货任务状态
            pickTask.setState(WareTaskConstant.PICK_STATE_OUTED);
            pickTaskService.updateById(pickTask);

            //step4.修改库存
            Integer inventoryId = pickTask.getInventoryId();
            Inventory inventory = inventoryService.getById(inventoryId);
            inventory.setAllotQuantity(inventory.getAllotQuantity() - pickTask.getPickQuantity());
            inventory.setQuantity(inventory.getQuantity() - pickTask.getPickQuantity());
            inventoryService.updateById(inventory);
            if (inventory.getQuantity() == 0) {
                inventoryService.removeById(inventoryId);
            }

            //step5.修改so单状态
            List<SoDetail> soDetailList = soDetailService.findByBillNo(soDetail.getBillNo());
            Boolean soDelivery = true;
            SoMaster soMaster = soMasterService.findBy("bill_no", soDetail.getBillNo());
            for (SoDetail soDetail1 : soDetailList) {
                if (soDetail1.getState() != 3) {
                    soDelivery = false;
                }
                soMaster.setState(7);//部分发货
                soMasterService.updateById(soMaster);
            }
            if (soDelivery) {
                soMaster.setState(8);//全部发货
                soMasterService.updateById(soMaster);
            }
        }

        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/getPickTasksForSeeding")
    public Result getPickTasksForSeeding(String waveCode, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }
        PickTaskCriteria criteria = new PickTaskCriteria();
        criteria.setWaveCode(waveCode);
        List<PickTaskDto> list = pickTaskService.findList(criteria);
        return ResultGenerator.genSuccessResult(new PageInfo(list));
    }

    @GetMapping("/findByWaveMasterId")
    public Result findByWaveMasterId(PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());

        List<PickTaskDto> list = pickTaskService.findByWaveMasterId(criteria);
        return ResultGenerator.genSuccessResult(new PageInfo(list));
    }

    @PostMapping("/getSeedingWallAlertInfo")
    public Result getSeedingWallAlertInfo(@RequestBody PickTaskCriteria criteria, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }
        List<SeedingWallAlertInfo> list = pickTaskService.getSeedingWallAlertInfo(criteria);
        PageInfo pageInfo = new PageInfo(list);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @Transactional
    @GetMapping("/updateSeededQuantity")
    public Result updateSeededQuantity(String soNo, String itemCode, Double quantity, Integer inventoryId, @ApiIgnore @User CurrentUser currentUser) {
        if (currentUser == null) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }
        PickTaskCriteria taskCriteria = new PickTaskCriteria();
        taskCriteria.setBillNo(soNo);
        taskCriteria.setItemCode(itemCode);
        taskCriteria.setInventoryId(inventoryId);
        List<PickTaskDto> pickTasks = pickTaskService.findList(taskCriteria);
        for (PickTask pickTask : pickTasks) {
            Double pickQuantity = pickTask.getPickQuantity();
            Double seededQuantity = pickTask.getSeededQuantity();
            Double neededQuantity = pickQuantity - seededQuantity;
            if (quantity > neededQuantity) {
                pickTask.setSeededQuantity(pickQuantity);
                quantity -= neededQuantity;
            } else if (quantity <= neededQuantity) {
                pickTask.setSeededQuantity(seededQuantity + quantity);
                pickTaskService.updateById(pickTask);
                break;
            }
            pickTaskService.updateById(pickTask);
        }
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "拣货确认", notes = "PDA")
    @ApiImplicitParams({@ApiImplicitParam(name = "access-token", value = "token", paramType = "header", dataType = "String", dataTypeClass = String.class, required = true)})
    @PostMapping("/commitPick")
    @Transactional
    public Result commitPick(@RequestBody CommitPickTask commitPickTask, @ApiIgnore @User CurrentUser currentUser) {
//        if (ObjectUtil.isEmpty(commitPickTask.getToBoxCode())) {
//            Inventory inventory = inventoryService.getOne(new QueryWrapper<>().eq("box_code", commitPickTask.getSrcBoxCode()));
//            inventory.getQuantity()
//            commitPickTask.setToBoxCode(commitPickTask.getSrcBoxCode());
//
//        }
        //Step1.校验
        // 目标容器是否有值，没有值则取系统的默认值
        Integer pickTaskId = commitPickTask.getPickTaskId();
        PickTask pickTask = pickTaskService.getById(pickTaskId);
        pickTask.setToBoxCode(codeRuleService.generateCellCodeRedis());
        String toCellCode = commitPickTask.getToCellCode();
        if (StringUtils.isEmpty(toCellCode)) {
            toCellCode = cellInfoService.getSysJhCell(commitPickTask.getWareId());
        }
        pickTask.setToCellCode(toCellCode);
//        pickTask.setToBoxCode(commitPickTask.getToBoxCode());
        pickTask.setReviewQuantity(commitPickTask.getDiffQty());

        //Step2.拣货确认
        pickTaskService.commitPick(pickTask, currentUser);
        //Step3 回传ERP
        List<OutDetail> outDetails = new ArrayList<>();
        PickTask sendPickTask = pickTaskService.getById(pickTask.getPickTaskId());
        sendPickTask.setState(5);
        Integer inventoryId = sendPickTask.getInventoryId();
        Inventory inventory = inventoryService.getById(inventoryId);
        OutDetail outDetail = new OutDetail();
        SoDetail soDetail = soDetailService.getById(sendPickTask.getSoDetailId());
        pickTaskService.updateById(pickTask);
        soDetail.setDeliveryQuantity(soDetail.getDeliveryQuantity() + pickTask.getPickQuantity());
        soDetail.setPickTime(LocalDateTime.now());
        BeanUtils.copyProperties(soDetail, outDetail);
        outDetail.setDeliveryQuantity(pickTask.getPickQuantity()); //数量
        outDetail.setBoxCode(inventory.getBoxCode());
        outDetail.setCellCode(inventory.getCellCode());
        outDetail.setInvId(inventoryId);
        outDetail.setBatchName(inventory.getBatchName());
        outDetail.setErpAreaId(inventory.getErpAreaId());
        outDetail.setMemo(soDetail.getMergeNo());
        outDetails.add(outDetail);

        String billNo = soDetail.getBillNo();
        SoMaster soMaster = soMasterService.getOneByField("bill_no", billNo);
        pickTaskService.updateById(sendPickTask);
        soDetailService.updateById(soDetail);
        List<SoMaster> soMasterList = new ArrayList<>();
        if (soMaster.getSoType() == 24) {
            List<SoMaster> soMasters = soMasterService.list(new QueryWrapper<SoMaster>().eq("bill_no", billNo));
            Map<String, SoMaster> soMasterMap = convertMap(soMasters, SoMaster::getBillNo);
            soMasterMap.forEach((key, val) -> {
                if (ObjectUtil.isEmpty(val)) {
                    return;
                }
                if (soMasterService.dispatch(val.getOrderBillNo())&&val.getDispatch()!=2) {
                    val.setDispatch(1);
                } else {
                    val.setDispatch(0);
                }
            });
            soMasterList.addAll(soMasterMap.values());
        }
        //齐套
        soMasterService.updateBatchById(soMasterList);
        if (ObjectUtil.isNotEmpty(soMaster.getBillType())) {
            strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());
        } else {
            switch (soMaster.getSoType()) {
                //调拨单
                case 41:
                    soMaster.setSoType(101);
                    break;
                //其他出库单
                case 29:
                    soMaster.setSoType(100);
                    break;
            }
            strategyErpService.resolveSo(soMaster, outDetails, new BaseAssist());
        }
        if (ObjectUtil.isNotEmpty(inventoryId)) {
        inventoryService.removeById(inventoryId);
        }

        return ResultGenerator.genSuccessResult();

    }


    @GetMapping("/getBoxStock")
    public Result getBoxStock(String boxCode, Integer pickTaskId) {
        PickTask pickTask = pickTaskService.getById(pickTaskId);
        Integer inventoryId = pickTask.getInventoryId();
        Inventory inventory = inventoryService.getById(inventoryId);
//        List<Inventory> inventories = inventoryService.getBoxStock(boxCode);
//        if (inventories.size() == 0) {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未查询到容器：[" + boxCode + "]的库存");
//        }
//        if (inventories.size() > 1) {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器：" + boxCode + "库存数据不唯一");
//        }
        return ResultGenerator.genSuccessResult(inventory);
    }

    @GetMapping("getBoxesByBillNo")
    public Result getBoxesByBillNo(String billNo) {
        SoMaster soMaster = soMasterService.getOne(new QueryWrapper<SoMaster>().eq("bill_no", billNo));
        List<PickTask> list;
//        if (WareTaskConstant.SO_STATE_PICKED.equals(soMaster.getState())) {
        list = pickTaskService.list(new QueryWrapper<PickTask>().eq("so_master_id", soMaster.getSoMasterId())
                .eq("state", 2)
        );
//        list = pickTaskService.getListByField("so_master_id", soMaster.getSoMasterId());

//        } else {
//            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未全部拣货");
//        }
        return ResultGenerator.genSuccessResult(list);
//        List<PickTask> pickTaskList = pickTaskService.list(new QueryWrapper<PickTask>().eq("bill_no", billNo));

    }

    @ApiOperation(value = "发货复核", notes = "支持按单发货和波次发货两种场景")
    @GetMapping("/getBoxesForSend")
    @Transactional
    public Result getBoxesForSend(@RequestParam String boxCode) {
        //Step1.校验
        //判断库存，判断是否在发货区
//        Inventory inventory = inventoryService.getOneByField("box_code", boxCode);

        List<Inventory> inventories = inventoryService.list(new QueryWrapper<Inventory>().eq("box_code", boxCode));
        if (ObjectUtil.isEmpty(inventories)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器" + boxCode + "查询不到库存");
        }

        Inventory inventory = inventories.get(0);
        String cellCode = inventories.get(0).getCellCode();

        Integer cellType = cellInfoService.getCellType(cellCode, inventory.getWareId());
        if (ObjectUtil.notEqual(BaseSystemConstant.CELL_USE_TYPE_COLLECTION, cellType)) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "容器库存" + boxCode + "不在发货区");
        }
        //Step2.查询
        List<PickTask> list;
        PickTask pickTask = pickTaskService.getOneByField("inventory_id", inventory.getInventoryId());
        if (ObjectUtil.isNotNull(pickTask.getSoMasterId())) {
            //按单发货逻辑
            SoMaster soMaster = soMasterService.getById(pickTask.getSoMasterId());
            if (WareTaskConstant.SO_STATE_PICKED.equals(soMaster.getState())) {
                list = pickTaskService.getListByField("so_master_id", soMaster.getSoMasterId());
            } else {
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未全部拣货");
            }
            //用于前台显示对应的出库任务
            list.get(0).setMemo(soMaster.getBillNo());
        } else {
            //波次发货逻辑
            Integer pickUserId = pickTask.getPickUserId();
            //根据拣货人查询到执行中的波次明细
            QueryWrapper<WaveDetail> qw = new QueryWrapper<>();
            qw.eq("pick_user_id", pickUserId);
            qw.in("state", WareTaskConstant.WAVE_STATE_PICKING, WareTaskConstant.WAVE_STATE_ALL_ALOT);
            List<WaveDetail> waveDetails = waveDetailService.list(qw);
            List<Integer> waveIds = waveDetails.stream().map(WaveDetail::getWaveDetailId).collect(Collectors.toList());

            //找到波次明细对应的拣货任务
            QueryWrapper<PickTask> qw2 = new QueryWrapper<>();
            qw2.eq("state", WareTaskConstant.PICK_STATE_ALLPICK);
            qw2.in("wave_detail_id", waveIds);

            list = pickTaskService.list(qw2);
        }
        return ResultGenerator.genSuccessResult(list);
    }

    @ApiOperation(value = "发货复核", notes = "按照波次单号查询")
    @GetMapping("/getBoxesForSend2")
    public Result getBoxesForSend2(@RequestParam String waveCode) {
        //Step2.查询
        QueryWrapper<PickTask> qw = new QueryWrapper<>();
        qw.eq("state", WareTaskConstant.PICK_STATE_ALLPICK);
        qw.eq("wave_code", waveCode);
        List<PickTask> tasks = pickTaskService.list(qw);
        List<PickTask> collect = tasks.stream().limit(20).collect(Collectors.toList());
        return ResultGenerator.genSuccessResult(collect);
    }

    @ApiOperation(value = "发货复核", notes = "按照波次单号查询")
    @GetMapping("/getBoxesForAll")
    public Result getBoxesForAll(@RequestParam String waveCode, @ApiIgnore @User CurrentUser currentUser) {
        //Step2.查询
        QueryWrapper<PickTask> qw = new QueryWrapper<>();
        qw.eq("state", WareTaskConstant.PICK_STATE_ALLPICK);
        qw.isNotNull("wave_code");
        List<PickTask> tasks = pickTaskService.list(qw);

        tasks = tasks.stream().filter(task -> task.getPickUserId().equals(currentUser.getUserId())).collect(Collectors.toList());

        List<WaveMaster> waveMasterList = new ArrayList<>();
        if (tasks.size() > 0) {
            Set<String> wacodes = tasks.stream().map(PickTask::getWaveCode).collect(Collectors.toSet());
            QueryWrapper<WaveMaster> qw2 = new QueryWrapper<>();
            qw2.in("code", wacodes);
            waveMasterList = waveMasterService.list(qw2);
        }

        return ResultGenerator.genSuccessResult(waveMasterList);
    }

    @ApiOperation(value = "查询拣货单")
    @PostMapping("/picking/list")
    public Result selectPickingList(@RequestBody PickTaskCriteria criteria) {
        // 设置页面的分页条件
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        // 使用MybatisPlus的QueryWrapper进行查询就不用自己写sql了
        QueryWrapper<PickTask> qw = new QueryWrapper<>();
//        Map<String, Object> map = new HashMap<>(3);
        // 设置状态为 0-待拣货 (0-待拣货  1-部分拣货  2-拣货完成  3-取消拣货  4-被合并 5-已发运)
        criteria.setState(WareTaskConstant.PICK_STATE_PROCESSING);
        // 设置查询条件
//        map.put("ware_id", criteria.getWareId());
//        map.put("so_master_id", criteria.getFindBySoMasterId());
//        map.put("state",criteria.getState());
        qw.eq("ware_id", criteria.getWareId());
        if (ObjectUtil.isNotNull(criteria.getFindBySoMasterId())) {
            qw.eq("so_master_id", criteria.getFindBySoMasterId());
        }
        qw.ne("state", criteria.getState());
//      List<PickTaskVo> pickingList = pickTaskService.list(qw.allEq(map, false));
        List<PickTask> pickingList = pickTaskService.list(qw);
        // 封装分页的数据
        PageInfo pageInfo = new PageInfo(pickingList);
        // 返回成功的结果
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @GetMapping("pickTask")
    public void pickTask() {
        pickTaskService.pickTask();
    }


    @GetMapping("/pickAndSendOut")
    @Transactional
    public Result pickAndSendOut(String pickIds, Integer erpAreaId, @ApiIgnore @User CurrentUser currentUser, String agreementNo) {
        if (ObjectUtil.isNull(currentUser)) {
            return ResultGenerator.genFailResult(CommonCode.MISSING_PERMISSION_PARAMTER);
        }
        List<PickTask> pickTasks = pickTaskService.listByIds(Arrays.asList(pickIds.split(",")));
        for (PickTask pickTask : pickTasks) {
            //特殊情况，拣货数量直接等于计划数量
            //这里也支持部分拣货的情况
            pickTask.setReviewQuantity(pickTask.getPickQuantity());
        }
        String cellCode = cellInfoService.findErpAreaId(erpAreaId);
        soMasterService.allot(pickIds, cellCode);
        //扣减库存，生成出库单
        pickTaskService.pickAndSendOut(pickTasks, currentUser, erpAreaId);

        return ResultGenerator.genSuccessResult();
    }

}
